#include <math.h>
#include "Vector.h"
namespace Math{

    Vector::Vector(){
        x=y=z=0.0f;
		w=1.0f;
    }

    Vector::Vector(float X,float Y, float Z){
        x=X;
        y=Y;
        z=Z;
		w=1.0f;
    }

    float Vector::dot(const Vector &b){
        return x*b.x+y*b.y+z*b.z;
    }

    Vector Vector::cross(const Vector &b){
        return Vector(y*b.z-z*b.y,
                      z*b.x-x*b.z,
                      x*b.y-y*b.x);
    }

	Vector Vector::inverse(){
		return Vector(-x, -y, -z);
	}

    Vector Vector::operator*(const float f){
        return Vector(x*f,y*f,z*f);
    }
	Vector Vector::operator*(const Matrix &mat){
		Vector result;
		
		result.x = x*mat(0,0) + y*mat(1,0) + z*mat(2,0) + mat(3,0);
		result.y = x*mat(0,1) + y*mat(1,1) + z*mat(2,1) + mat(3,1);
		result.z = x*mat(0,2) + y*mat(1,2) + z*mat(2,2) + mat(3,2);
		result.w = x*mat(0,3) + y*mat(1,3) + z*mat(2,3) + mat(3,3);

		result.x = result.x / result.w;
		result.y = result.y / result.w;
		result.z = result.z / result.w;
		result.w = 1.0f;

		return result;
	}

	Vector Vector::operator/(const float n){
		return Vector(x/n, y/n, z/n);
	} 
    Vector Vector::operator+(const Vector &o){
        return Vector(x+o.x,y+o.y,z+o.z);
    }
    Vector Vector::operator-(const Vector &o){
        return Vector(x-o.x,y-o.y,z-o.z);
    }
    void Vector::operator+=(const Vector &o){
        x+=o.x;y+=o.y;z+=o.z;
    }
    void Vector::operator-=(const Vector &o){
        x-=o.x;y-=o.y;z=-o.z;
    }
	void Vector::operator*=(const float n){
		x*=n;y*=n;z*=n;
	}

	void Vector::operator*=(const Matrix &mat){
		float _x = x*mat(0,0) + y*mat(1,0) + z*mat(2,0) + mat(3,0);
		float _y = x*mat(0,1) + y*mat(1,1) + z*mat(2,1) + mat(3,1);
		float _z = x*mat(0,2) + y*mat(1,2) + z*mat(2,2) + mat(3,2);
		float _w = x*mat(0,3) + y*mat(1,3) + z*mat(2,3) + mat(3,3);

		x = _x / _w;
		y = _y / _w;
		z = _z / _w;
		w = 1.0f;
	}

	void Vector::operator/=(const float n){
		x/=n;y/=n;z/=n;
	}
    bool Vector::operator==(const Vector &o){
        return x==o.x && y==o.y && z==o.z;
    }
	bool Vector::operator!=(const Vector &o){
		return x!=o.x || y!=o.y || z!=o.z;
	}

    float Vector::norm(){
        return sqrt(x*x+y*y+z*z);
    }
    Vector Vector::normal(){
        return (*this)*(1/norm());
    }     
    void Vector::normalize(){
        float n =norm();
        x/=n;y/=n;z/=n;
    }    

}; 
